package lib.base;

import lib.data.Customer;
import lib.data.Employee;
import lib.json.JSONUnserializer;
import lib.modules.EventGadget;
import lib.modules.ModAccountMove;
import lib.modules.ModAdmin;
import lib.modules.ModLeaveAccount;
import lib.modules.ModLeaveRequests;
import lib.modules.ModRegister;
import lib.modules.SidebarGadget;
import lib.translation.Translator;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.naming.InitialContext;
import javax.sql.DataSource;


/**
 * The Class EgoSystem.
 */
public class EgoSystem
{
	/** The config file
	 * - @notice WebContent/modules/sidebar/gadget.xml cannot read this config
	 */
	static public String configFile = "/usr/share/etapps/leave_manager-config.json";
	
	/** The db connection. */
	static public Connection dbConnection;
	
	/** The customers. */
	static private Map<String, Customer> _customers = new HashMap<String, Customer>();
	
	/** The auth. */
	private EgoAuth _auth;
	
	/** The module. */
	private EgoModule module;

	/** The request. */
	private HttpServletRequest _request = null;
	
	/** The response. */
	private HttpServletResponse _response = null;
	
	/** The log_messages. */
	static String _logMessages = "";
	
	/** Translator - for each language one */
	static public HashMap<String, Translator> translator = null;
	
	/** is working */
	static public boolean isWorking = false;
	
	/** configuration */
	static public HashMap<String, Object> config = null;
	
	/**
	 * construct
	 */
	public EgoSystem(HttpServletRequest request, HttpServletResponse response)
	{
		this._request = request;
		this._response = response;
	}
	
	/**
	 * Make a HTTP-Request (GET).
	 * 
	 * @param url the url
	 * 
	 * @throws Exception the exception
	 * 
	 * @return String Content
	 */
	static public String httpRequest(String url) throws Exception
	{
		URL url_obj = new URL(url);
		HttpURLConnection con = (HttpURLConnection) url_obj.openConnection();
		con.setRequestMethod("GET");
		InputStreamReader content = new InputStreamReader(con.getInputStream());
		String content_str = "";
		int chr;
		while ((chr = content.read()) != -1)
		{
			content_str+= (char)chr;
		}
		content.close();

		return content_str;
	}
	
	/**
	 * startup
	 * only the first time.
	 * 
	 * @throws Exception the exception
	 * 
	 * @return void
	 */
	static public void startup() throws Exception
	{
		/*
		 * Start DB Connection
		 * 
		 * @see http://dev.mysql.com/doc/refman/5.1/en/connector-j-usagenotes-j2ee.html
		 */
		InitialContext ctx = new InitialContext();
		DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");
		dbConnection = ds.getConnection();
		
		loadConfig();
		
		// for each language one translator
		translator = new HashMap<String, Translator>();
		ArrayList<String> langs = Translator.getLanguages();
		for (int i=0; i<langs.size(); i++)
		{
			translator.put(langs.get(i), new Translator(langs.get(i)));
		}
	}
	
	@SuppressWarnings("unchecked")
	static public void loadConfig() throws EgoException
	{
		/*
		 * load configuration file
		 */
		try {
			BufferedReader br = new BufferedReader(new FileReader(configFile));
			String c = "", zeile;
			
			while ((zeile = br.readLine()) != null) 
			{
				c += zeile;
			}
			config = (HashMap<String, Object>) new JSONUnserializer().unserialize(c);
		} catch (Exception e)
		{
			throw new EgoException(EgoException.CONFIG_FILE_NOT_READABLE, e);
		}
		// check config
		if (
			EgoSystem.config.get("host") == null
			|| EgoSystem.config.get("path") == null
			|| EgoSystem.config.get("language-files") == null
			|| EgoSystem.config.get("temporarySystemAccounts") == null
		) {
			throw new EgoException(EgoException.CONFIG_FILE_NOT_READABLE);
		}
	}
	
	/**
	 * load data objects - Customer,Departments,Employees ...
	 * do auth.
	 * 
	 * 
	 * @throws Exception the exception
	 * 
	 * @return void
	 */
	public void prepend() throws Exception
	{	
		// reset log
		_logMessages = "";
		
		// disable browser cache
		_response.setHeader("Cache-Control", "no-cache, must-revalidate");
		
		// set UTF 8
		_response.setCharacterEncoding("utf-8");
		_request.setCharacterEncoding("UTF-8");
		
		_auth = new EgoAuth(_request);
		boolean logged = _auth.start();
		if (!logged) return;
		_request.getSession().setAttribute("auth", _auth);
		
		// load customer
		int id = -1;
		try {
			id = Customer.getIdByMail((String) _request.getSession().getAttribute("email"));
		} catch (Exception e)
		{
			/*
			 * the first connection after a long time with no communication
			 * brings an error, so we try it again
			 */
			if (!_request.getParameter("mdl").equals("register"))
			{
				id = Customer.getIdByMail((String) _request.getSession().getAttribute("email"));
			}
		}

		if (id != -1 && _customers.get(Integer.toString(id)) == null)
		{
			_customers.put(
				Integer.toString(id),
				new Customer(id)
			);
		}
		
		// save current customer in session
		_request.getSession().setAttribute(
			"currentCustomer"
			, _customers.get(Integer.toString(id))
		);
		// save current employee in session
		Employee curEmp;
		try {
			curEmp = _customers.get(Integer.toString(id)).getEmployeeByMail((String) _request.getSession().getAttribute("email"));
		} catch (Exception e)
		{
			// i'm not an employee -> systemAccount - only administrator
			curEmp = null;
		}
		_request.getSession().setAttribute(
			"currentEmployee"
			, curEmp
		);
		
		// set language, if not got from google account settings (EgoAuth)
		if (_request.getSession().getAttribute("language") == null)
		{
			_request.getSession().setAttribute(
				"language"
				, "en"
			);
		}
	}
	
	/**
	 * handle query parameters.
	 * 
	 * @throws Exception the exception
	 * 
	 * @return void
	 */
	public void work() throws Exception
	{
		if (!_auth.isLogged())
		{
			// have to log in
			_request.getSession().setAttribute("template", "login.jsp");
		} else
		{
			/*
			 * define Module Class
			 */
			if (_request.getParameter("mdl").equals("event"))
			{
				module = new EventGadget(_request);
			} else if (_request.getParameter("mdl").equals("sidebar"))
			{
				module = new SidebarGadget(_request);
			} else if (_request.getParameter("mdl").equals("admin"))
			{
				module = new ModAdmin(_request);
			} else if (_request.getParameter("mdl").equals("leave_account"))
			{
				module = new ModLeaveAccount(_request);
			} else if (_request.getParameter("mdl").equals("leave_requests"))
			{
				module = new ModLeaveRequests(_request);
			} else if (_request.getParameter("mdl").equals("register"))
			{
				module = new ModRegister(_request);
			} else if (_request.getParameter("mdl").equals("account_move"))
			{
				module = new ModAccountMove(_request);
			}

			module.work();
		}
	}
	
	/**
	 * logging function.
	 * 
	 * @param message String
	 * 
	 * @return void
	 */
	static public void log(String message)
	{
		_logMessages+=message+"\n";
	}
	
	/**
	 * logging function
	 * returns the current log.
	 * 
	 * @return String log
	 */
	static public String log()
	{
		return _logMessages;
	}
}
